# Title: 硬件故障统计汇总
# Params: start_time|one_str|2024-09-04, end_time|one_str|2024-09-04

import datetime
import re
import warnings
from random import randint
import json
import requests
from requests import ReadTimeout
from openpyxl.workbook import Workbook

warnings.filterwarnings("ignore")


class YunGe:
    def __init__(self, host, port, start_time, end_time):
        self.base_url = f'https://{host}:{port}'
        self.headers = {
            "accept": "*/*",
            "accept-language": "zh-CN,zh;q=0.9",
            "content-type": "application/json;charset=UTF-8",
            "sec-ch-ua": "\"Not_A Brand\";v=\"99\", \"Google Chrome\";v=\"109\", \"Chromium\";v=\"109\"",
            "sec-ch-ua-mobile": "?0",
            "sec-ch-ua-platform": "\"Windows\"",
            "sec-fetch-dest": "empty",
            "sec-fetch-mode": "cors",
            "sec-fetch-site": "same-origin",
            "Referer": f"https://{host}:{port}/front/",
            "Referrer-Policy": "strict-origin-when-cross-origin"
        }
        self.cookies = {
            "sso_t_name": "uniToken",
            "sso_t_value": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJpcFwiOlwiMTk3LjE2Ni4yMzQuMTI4XCIsXCJuYW1lXCI6XCLllJDluIVcIixcIm1vYmlsZVwiOlwiMTg4ODYwMjU0NzRcIixcImFjY291bnRcIjpcImR3dGFuZ3NodWFpXCIsXCJzdWJBY2NvdW50XCI6XCJkd3RhbmdzaHVhaVwifSIsIm5iZiI6MTcxMDQ2Njc5NywiaXNzIjoicG9ydGFsLXN0ZXdhcmQiLCJleHAiOjE3MTA0NjY4NTcsImlhdCI6MTcxMDQ2Njc5NywianRpIjoiOWVhZGFkM2E4ZmViNDQ0YmI5ZjM1Y2IyYzdlMmVhNTUifQ.q1CiKZOeD_7Kyvl9PbzOPmFkd7ObAYOXcRf8oYxq3SU"
        }
        self.start_time = start_time
        self.end_time = end_time

    def request_get(self, uri, params=None):
        if not ''.startswith('/'):
            uri = '/' + uri
        retry = 0
        while retry < 30:
            try:
                resp = requests.get(self.base_url + uri, headers=self.headers, params=params, verify=False,
                                    cookies=self.cookies, timeout=5)
                if resp.status_code != 200:
                    raise ValueError(f'接口请求失败：{resp.text}')
                return resp.json()
            except ReadTimeout:
                print('接口请求重试', retry)
                retry += 1

        raise ValueError(f'{uri} 请求重试超限')

    def request_post(self, uri, params):
        if not ''.startswith('/'):
            uri = '/' + uri

        retry = 0
        while retry < 30:
            try:
                resp = requests.post(self.base_url + uri, headers=self.headers, data=json.dumps(params), verify=False,
                                     timeout=5)
                if resp.status_code != 200:
                    raise ValueError(f'接口请求失败：{resp.text}')
                return resp.json()
            except ReadTimeout:
                print('接口请求重试', retry)
                retry += 1

        raise ValueError(f'{uri} 请求重试超限')

    def get_token(self):
        uri = "/uc/sso/auth"
        params = {
            "code": "SHA3RTNqSW95WGlOd0lNQXlSeEFGQT09",
            "service": "s",
            "type": "umsToken"
        }
        result = self.request_get(uri, params=params)
        if result:
            self.headers['authorization'] = "Bearer " + result['token']
        else:
            raise ValueError('获取token失败')

    def detail(self, id):
        uri = '/runtime/runtime/instance/v1/getInstFormAndBONew?identification=data&proInstId=' + id
        return self.request_get(uri)

    def annex_content(self, file_id):
        uri = '/portal/system/file/v1/downloadFile?fileId=' + file_id
        resp = self.request_get(uri)
        if resp.status_code != 200:
            raise ValueError(f'接口请求失败：{resp.text}')
        return resp.content.decode()

    def download(self, filename, file_id):
        url = self.base_url + '/portal/system/file/v1/downloadFile?fileId=' + file_id
        resp = requests.get(url, headers=self.headers, verify=False)
        if resp.status_code != 200:
            raise ValueError(f'接口请求失败：{resp.text}')

        with open(filename, "wb") as code:
            code.write(resp.content)

        return True

    def list_event(self):
        uri = "/runtime/runtime/instance/statistic/v1/list"
        params = {
            "proc_def_key": "xtsjgzlc",
            "resource_pool": "贵阳资源池",
            "start_date": self.start_time,
            "end_date": self.end_time,
            "solve_person": [],
            "org_id": "",
            "query_key": "",
            "subject": "",
            "recordId": "",
            "instanceName": "",
            "page_size": 1000,
            "page_no": 1,
            "status": "",
            "department1": "",
            "department2": ""
        }
        return self.request_post(uri, params=params)


def random_time(start_time):
    create_time = datetime.datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S")
    return create_time + datetime.timedelta(minutes=randint(60, 300))


def get_value(pattern, content):
    _value = re.findall(pattern, content)
    if not _value:
        _console(f'匹配内容异常：{pattern}目标\n{content}')
        return '无'
    return _value[0].strip()


def main(start_time: str = '2024-08-02', end_time: str = '2024-8-8'):
    try:
        start_time_ = datetime.datetime.strptime(start_time, '%Y-%m-%d').date().__str__()
        end_time_ = datetime.datetime.strptime(end_time, '%Y-%m-%d').date().__str__()
    except Exception as e:
        return '日期输入错误！' + str(e)

    all_create_time = []
    all_no = []
    all_fault_detail = []
    all_fault_flowable = []

    yg = YunGe('172.17.42.253', 28080, start_time_, end_time_)
    # yg = YunGe('172.21.152.199', 10372, start_time, end_time)
    yg.get_token()

    # 处理系统事件跟踪单
    event_order = yg.list_event()

    if event_order.get('count') != len(event_order.get('result')):
        return '事件跟踪单 获取的数量异常'

    if event_order.get('result'):
        orders = event_order['result']
        orders.sort(key=lambda x: x['createTime'])
        orders = [x for i, x in enumerate(orders) if not i % 2]
        print('工单数量：', len(orders))
        for item in orders:
            if item['id'] == '202408263393476':
                continue
            detail = yg.detail(item['id'])['data']['xtsjgzdx']
            
            fault_detail = detail['sjms']
            if '、' in fault_detail:
                fault_detail = fault_detail.replace('、', '\n')
            for current_fault in fault_detail.split('贵池'):
                if len(current_fault) < 10:
                    continue
                current_fault = '贵池' + current_fault

                all_fault_detail.append(current_fault)
                all_create_time.append(item['createTime'])
                all_no.append(item['id'])
                all_fault_flowable.append(detail)

    _console(f"总工单：{len(all_fault_detail)}条")
    _console(f"总故障数量：{len(all_create_time)}条")
    result_data = []
    fault_text = '\n'.join(all_fault_detail)

    index = 0
    for current_fault in fault_text.split('贵池'):
        if len(current_fault) < 10:
            continue
        current_fault = '贵池' + current_fault

        re_theme = get_value(r'(贵池-.*)', current_fault)
        re_title = get_value(r'贵池.*\d(.*)', current_fault)
        re_modal = get_value(r'机型[:|：](.*)', current_fault)
        re_IPMI = get_value(r'IPMI：(.*)', current_fault)
        re_manageIP = get_value(r'管理IP[:|：](.*)', current_fault)
        re_sn = get_value(r'SN\(序列号\)[:|：](.*)', current_fault)
        re_business = get_value(r'业务系统[:|：](.*)', current_fault)
        re_desc = get_value(r'故障描述[:|：](.*)', current_fault)
        re_idc = get_value(r'贵阳数据中心(.*)机房', current_fault)
        re_rack = get_value(r'机房(.*)', current_fault)
        re_brand = get_value(r'维保状态：(.*)', current_fault)
        try:
            result_data.append(
                [(index + 1), re_theme, '主机', re_title, all_create_time[index], random_time(all_create_time[index]),
                 re_IPMI, re_manageIP, re_desc, re_modal, re_brand, re_sn, re_business, '是', '贵阳数据中心',
                 re_idc, re_rack, '', all_no[index], all_fault_flowable[index].get('glgdbh', '无'),
                 all_fault_flowable[index].get('sjwtly'),
                 '满意', '吴林', '无', '无', '无']
            )
        except IndexError:
            print(f'{all_no[index]} 格式错误\n{current_fault}')
        index += 1

    wb_result = Workbook()
    ws_result = wb_result.active
    ws_result.append(
        ['序号', '主题', '设备类型', '故障分类', '故障开始时间', '故障消除时间', 'IPMI ip', '管理ip', '故障描述',
         '主机型号','厂家', '设备序列号', '业务系统', '收集日志提供给厂家时间', '数据中心', '机房',
         '机柜', 'EOMS故障单号', '系统事件跟踪单号', '关联单号', '事件来源', '厂家配合度', '卓望责任人', '厂家责任人'])

    for item in result_data:
        ws_result.append(item)

    save_file = f'故障历史-{datetime.datetime.now().strftime("%Y%m%d%H%M%S")}.xlsx'
    wb_result.save(save_file)

    return f"文件已保存至：{save_file}"

# if __name__ == '__main__':
#     script_name = '硬件故障统计汇总'
#     print('脚本名称：硬件故障')
#     main()
